﻿using System;
using System.Collections;
using System.ComponentModel;

namespace Borg.Framework
{
    public class DataSourceAdapter<T> : IBindingList
    {
        private readonly IDataModel<T> _model;
        private readonly object _syncRoot;

        public event ListChangedEventHandler ListChanged;

        public DataSourceAdapter(IDataModel<T> model)
        {
            _syncRoot = new object();
            _model = model;
            model.ListChanged += ModelChanged;
        }

        public int Add(object value)
        {
            throw new NotSupportedException();
        }

        public void AddIndex(PropertyDescriptor property)
        { }

        public object AddNew()
        {
            throw new NotSupportedException();
        }

        public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            throw new NotSupportedException();
        }

        public void Clear()
        {
            throw new NotSupportedException();
        }

        public bool Contains(object value)
        {
            return (IndexOf(value) != -1);
        }

        public void CopyTo(Array array, int index)
        {
            foreach (var o in this)
                array.SetValue(o, index++);
        }

        public int Find(PropertyDescriptor property, object key)
        {
            throw new NotSupportedException();
        }

        public IEnumerator GetEnumerator()
        {
            return _model.GetEnumerator();
        }

        public int IndexOf(object value)
        {
            var i = 0;

            foreach (var o in this)
            {
                if (o.Equals(value))
                    return i;

                i++;
            }

            return -1;
        }

        public void Insert(int index, object value)
        {
            throw new NotSupportedException();
        }

        private void ModelChanged(object sender, ListChangedEventArgs args)
        {
            if (ListChanged != null)
                ListChanged(this, args);
        }

        public void Remove(object value)
        {
            throw new NotSupportedException();
        }

        public void RemoveAt(int index)
        {
            throw new NotSupportedException();
        }

        public void RemoveIndex(PropertyDescriptor property)
        { }

        public void RemoveSort()
        {
            throw new NotSupportedException();
        }

        public bool AllowEdit
        {
            get { return false; }
        }

        public bool AllowNew
        {
            get { return false; }
        }

        public bool AllowRemove
        {
            get { return false; }
        }

        public int Count
        {
            get { return _model.Count; }
        }

        public bool IsFixedSize
        {
            get { return false; }
        }

        public bool IsReadOnly
        {
            get { return true; }
        }

        public bool IsSorted
        {
            get { throw new NotSupportedException(); }
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object this[int index]
        {
            get { return _model[index]; }
            set { throw new NotSupportedException(); }
        }

        public ListSortDirection SortDirection
        {
            get { throw new NotSupportedException(); }
        }

        public PropertyDescriptor SortProperty
        {
            get { throw new NotSupportedException(); }
        }

        public bool SupportsChangeNotification
        {
            get { return true; }
        }

        public bool SupportsSearching
        {
            get { return false; }
        }

        public bool SupportsSorting
        {
            get { return false; }
        }

        public object SyncRoot
        {
            get { return _syncRoot; }
        }
    }
}

